import { Component, OnInit, ViewChild, ViewChildren, QueryList, OnDestroy, OnChanges, SimpleChanges } from '@angular/core';
import { ITdDataTableColumn } from "@covalent/core";

import { UserFarmAlarmconfig } from "../../../entity/user_farm_alarmconfig.model";
import { Farm } from "../../../entity/farm.model";
import { AlarmCategory } from "../../../entity/alarm-category.model";
import { User } from "../../../entity/user.model";
import { UserAlarmconfig } from "../../../entity/user_alarmconfig.model";

import { FarmService } from "../../../service/farm.service";
import { UserAlarmconfigService } from "../../../service/user_alarmconfig.service";
import { FaultLevelService } from "../../../service/fault_level.service";
// import { PushService } from "../../../service/websocket-service/push.service";
import { AlarmCategoryService } from "../../../service/alarm-category.service";
import { UserFarmAlarmconfigService } from "../../../service/user-farm-alarmconfig.service";

import { AlarmCategoryData, FaultTableData } from "./alarm-category-data";
import { AlarmCategoryFarmData } from "./alarm-category-farm-data";

import { List } from 'linqts';
import { FaultLevel } from "../../../entity/fault-level.model";
import { FaultData } from "../../../entity/fault-data";
import { DataSourceService } from "../../../service/data-source/data-source.service";
import { AudioComponent } from "../../common/audio/audio.component";
import { ApplicationService } from '../../../service/application.service';


@Component({
  selector: 'app-alarm-lamp',
  templateUrl: './alarm-lamp.component.html',
  styleUrls: ['./alarm-lamp.component.css'],
  providers: [DataSourceService]
})
export class AlarmLampComponent implements OnInit, OnDestroy {

  private user: User = new User();
  public fadeDiv: boolean = false;
  public isLedFlash: boolean = true;
  public isSound: boolean = false;
  public soundVolume: number = 1;
  private isShowWindow: boolean = true;
  private lastTime: number = 5;
  /** 报警等级和声音*/
  private faultLevels: FaultLevel[] = [];
  private currMaxFaultLevel: FaultLevel;


  /**
   * 报警信息按报警分类进行汇总
   *
   * @type {AlarmCategoryFarmData[]}
   * @memberof AlarmLampComponent
   */
  public alarmCategoryDatas: AlarmCategoryData[] = [];
  public allAlarmCategoryDatas: AlarmCategoryData[] = [];
  /**
   * 报警信息按报警分类和风场进行汇总
   *
   * @type {AlarmCategoryFarmData[]}
   * @memberof AlarmLampComponent
   */
  public alarmCategoryFarmDatas: AlarmCategoryFarmData[] = [];


  /**
   * 未确认的报警数目
   *
   * @type {number}
   * @memberof AlarmLampComponent
   */
  public unConfirmAlarmTotal: number = 0;

  /**
   *
   *
   * @type {boolean}
   * @memberof AlarmLampComponent
   */
  public isAlarm: boolean = false;
  //单个播放数据模型构建
  public audios: AudioData[] = [];

  public active1: boolean = true;
  public active2: boolean = false;
  public active3: boolean = false;

  /**
   * 等级（模糊查询字段）
   * @type {string}
   * @memberof AlarmLampComponent
   */
  public faultLevelName: string = "";

  /**
   * 描述（模糊查询字段）
   * @type {string}
   * @memberof AlarmLampComponent
   */
  public desc: string = "";
  /**
   * 类别（模糊查询字段）
   * @type {string}
   * @memberof AlarmLampComponent
   */
  public components: string = "";

  /**
   * 状态（模糊查询字段）
   * @type {string}
   * @memberof AlarmLampComponent
   */
  public stateName: string = "";


  public timeout: any;
  /**
   * 升压站总数
   */
  public substationDataTotal:number = 0;
  /**
   * 设备预警总数
   */
  public earlyWarningDataTotal:number = 0;



  @ViewChildren(AudioComponent)
  audio: QueryList<AudioComponent>;
  /**
   *报警定时器
   *
   * @private
   * @type {*}
   * @memberof AlarmLampComponent
   */
  private timer: any;
  alarmShowCount = 200;
  constructor(
    private dataSource: DataSourceService,
    private farmService: FarmService,
    private userFarmAlarmconfigService: UserFarmAlarmconfigService,
    private alarmCategoryService: AlarmCategoryService,
    private userAlarmconfigService: UserAlarmconfigService,
    private faultLevelService: FaultLevelService,
    private application: ApplicationService

  ) {
    this.user.userId = 1;
  }

  ngOnInit() {
    if (this.application.currentApplicationParams && this.application.currentApplicationParams['alarmShowCount']) {
      this.alarmShowCount = Number(this.application.currentApplicationParams['alarmShowCount'].paramValue);
    }
    this.loadData();

  }
  ngOnDestroy(): void {
    if (this.dataSource != null)
      this.dataSource.dispose();
  }


  ngOnChanges(changes: SimpleChanges) {
    clearTimeout(this.timeout);
    this.timeout = setTimeout(() => {
      if (this.alarmCategoryDatas[0].faultTableDatas) {
        this.alarmCategoryFilter();
      }
    }, 200);
  }


  /**
   * 单条报警确认
   *
   * @param {FaultData} faultData
   * @memberof AlarmLampComponent
   */
  public onConfirm(faultData: FaultData) {
    faultData.confirm = true;
    this.totalUnConfirmAlarm();
  }

  /**
   * 全部确认
   *
   * @memberof AlarmLampComponent
   */
  public onAllConfirm() {
    this.alarmCategoryDatas.forEach(catagoryData => {
      // catagoryData.faultDatas.forEach(o => {
      //   if (!o.confirm) {
      //     o.confirm = true;
      //   }
      // });
      catagoryData.faultTableDatas.forEach(o => {
        if (!o.confirm) {
          o.confirm = true;
        }
      });
    });
    this.totalUnConfirmAlarm();
    this.endAlarm();
  }

  //告警
  /**
    public onAlarmCategoryClick(alarmCategpry: AlarmCategoryData) {
      alarmCategpry.isChecked = true;
      let alarmCategprys = this.alarmCategoryDatas.filter(o => o.alarmCategoryId != alarmCategpry.alarmCategoryId);
      if (alarmCategprys && alarmCategprys.length > 0) {
        alarmCategprys.map(o => o.isChecked = false);
      }

      if (this.alarmCategoryFarmDatas.length > 0) {
        this.alarmCategoryFarmDatas.map(o => {
          if (o.alarmCategoryId == alarmCategpry.alarmCategoryId) {
            o.isChecked = true;
          }
          else {
            o.isChecked = false;
          }
        });
      }

    }
  */
  public onFadeClick() {
    this.fadeDiv = !this.fadeDiv;
  }



  private clearAlarmCategoryMore() {
    this.alarmCategoryDatas.forEach((val) => {
      if (val.faultTableDatas.length > this.alarmShowCount) {
        val.faultTableDatas = val.faultTableDatas.slice(0, this.alarmShowCount);
      }
    });
    this.alarmCategoryFarmDatas.forEach(val => {
      val.farmFaultDatas.forEach(v => {
        if (v.faultFTableDatas.length > this.alarmShowCount) {
          v.faultFTableDatas = v.faultFTableDatas.slice(0, this.alarmShowCount);
        }
      })
    });
  }

  /**
   * 初始化数据2
   *
   * @param {AlarmCategory[]} categorys （报警和告警警）
   * @param {Farm[]} farms（风场集合）
   * @param {UserFarmAlarmconfig[]} configs （用户风场报警配置集合）
   * @memberof AlarmLampComponent
   */
  private initData(categorys: AlarmCategory[], farms: Farm[], configs: UserFarmAlarmconfig[]) {
    if (!categorys) { return false; }
    categorys.forEach((category, index) => {
      let alarmCategoryData = {
        alarmCategoryId: category.alarmCategoryId,
        alarmCategoryName: category.alarmCategoryName,
        faultDatas: [],
        faultTableDatas: [],
        isChecked: index === 0 ? true : false
      };
      let alarmCategoryFarmData: AlarmCategoryFarmData = {
        alarmCategoryId: category.alarmCategoryId,
        alarmCategoryName: category.alarmCategoryName,
        farmFaultDatas: [],
        isChecked: index === 0 ? true : false
      };
      this.alarmCategoryFarmDatas.push(alarmCategoryFarmData);

      farms.forEach(farm => {
        let index = configs.findIndex(o => o.farmId == farm.farmId && o.alarmCategoryId == category.alarmCategoryId);
        //查找风场是不是在用户风场报警配置中存在
        let config = index > 0 ? configs[index] : null;
        //只有当用户风场配置中存在对应的配置并且unAlarm配置为false时，当前用户才不订阅该风场,该报警分类下的报警信息
        if (!(config != null && !config.unAlarm)) {
          alarmCategoryFarmData.farmFaultDatas.push({
            farmId: farm.farmId,
            farmName: farm.farmName,
            faultDatas: [],
            faultFTableDatas: [],
            confirmTotal: 0
          });
        }
      });

      if (alarmCategoryFarmData.farmFaultDatas.length > 0) {
        this.alarmCategoryDatas.push(alarmCategoryData);
      }
    });

    this.allAlarmCategoryDatas = [...this.alarmCategoryDatas];
  }

  /**
   * 初始化播放器
   *
   * @memberof AlarmLampComponent
   */
  private initAudio(faultLevel: FaultLevel[], configs: UserAlarmconfig[]) {
    if (!configs) { return false; };
    //this.audio.autoplay = true;
    this.audio.forEach((v) => {
      v.controls = true;
    })
    configs.forEach(config => {
      switch (config.alarmConfigName) {
        case "IsLedFlash":
          let ledflash: string = config.alarmConfigValue as string;
          if (ledflash != null)
            this.isLedFlash = (ledflash == "true");
          break;
        case "IsSound":
          let sound: string = config.alarmConfigValue as string;
          if (sound != null)
            this.isSound = (sound == "true");
          break;
        case "IsShowWindow":
          let showWindow: string = config.alarmConfigValue as string;
          if (showWindow != null)
            this.isShowWindow = (showWindow == "true");
          break;
        case "SoundVolume":
          let SoundVolume: number = config.alarmConfigValue as number;
          if (SoundVolume != null)
            if (SoundVolume <= 1) {
              this.soundVolume = SoundVolume;
            }
          break;
        case "LastTime":
          let LastTime: number = config.alarmConfigValue as number;
          if (LastTime != null)
            this.lastTime = LastTime;
          break;
      }

    });
    if (!faultLevel) { return false; };
    //单个播放数据模型构建
    faultLevel.forEach((value, i) => {

      let audioData = {
        audioId: value.faultLevelId,
        audioSrc: value.content,
        volume: this.soundVolume,
        muted: false,
      }
      this.audios.push(audioData)
    })
  }

  /**
   * 加载数据111
   *
   * @memberof AlarmLampComponent
   */
  private loadData() {
    Promise.all([
      this.userAlarmconfigService.getUserAlarmconfigsByUserId(this.user.userId),
      this.userFarmAlarmconfigService.getUserFarmAlarmconfigsByUserId(this.user.userId),
      this.alarmCategoryService.getAlarmCategorys(),
      this.faultLevelService.getFaultLevelsWithSound(),
      this.farmService.getFarmsWithTotalTurbineByUserId(this.application.currentUser.userId)
      ])
      .then(res => {
        if (res[3]) {
          this.faultLevels.push(...res[3]);
        };

        this.initData(res[2], res[4], res[1]);
        this.initAudio(res[3], res[0]);
        this.subscribeAlarm();
      })
      .catch(error => {
        console.log("app-alarm-lamp has error", error);
      });
  }
  //升压站子组件给父组件传递的升压站总数
  onSubstationDataTotalChange(substationDataTotal){
    this.substationDataTotal = substationDataTotal
  }
  onEarlyWarningDataTotalChange(earlyWarningDataTotal){
    this.earlyWarningDataTotal = earlyWarningDataTotal
  }

  /**
   * 订阅故障数据333
   *
   * @memberof AlarmLampComponent
   */
  private subscribeAlarm() {
    this.dataSource
      .alarm(this.user.userId)
      .subscribe(
        next => {
          // console.log(next);
          let timeout: any;
          timeout = setTimeout(() => this.resolving(next, timeout));

          //this.faultDataSources.unshift(...next);
        });
  }

  /**
   *
   *
   * 解析故障报警数据444
   *
   * @private
   * @param {FaultData[]} faultDatas 推送过来的数据
   * @param {*} timer
   * @memberof AlarmLampComponent
   */
  private resolving(faultDatas: FaultData[], timer: any) {

    const faults = [...faultDatas];
    let faultsLsit: FaultTableData[] = [];
    faults.forEach(fault => {
      const currentFault = {
        alarmCategoryId: fault.alarmCategoryId,
        farmId: fault.farmId,
        faultCode: fault.faultCode,
        desc: fault.farmName + '-' + fault.deviceName + '-' + fault.faultDesc,
        faultLevelName: fault.faultLevelName,
        faultLevelId: fault.faultLevelId,
        faultLevelColor: fault.faultLevelColor,
        components: fault.turbComponentName + '-' + fault.subcomponentName + '-' + fault.partsName,
        faultTime: fault.faultTime,
        confirm: fault.confirm
      };
      faultsLsit.push(currentFault);
    });
    // 单前报警等级
    this.currMaxFaultLevel = null;
    // let list = new List(faultDatas);
    let list = new List(faultsLsit);
    // 按报警分类分组,
    let categoryGroups = list.GroupBy(g => g.alarmCategoryId, m => m);
    // 获得报警分类Id,
    let categoryIds = Object.getOwnPropertyNames(categoryGroups);


    this.alarmCategoryDatas.forEach((item, index) => {
      if (this.allAlarmCategoryDatas[index].faultTableDatas.length > this.alarmShowCount) {
        this.allAlarmCategoryDatas[index].faultTableDatas.slice(0, this.alarmShowCount);
      }
    });
    categoryIds.forEach(categoryId => {
      let alarmCategoryId: number = Number.parseInt(categoryId);
      // 根据报警分类Id,查询本地存放的报警集合对象
      let alarmCategoryData = this.alarmCategoryDatas.find(o => o.alarmCategoryId === alarmCategoryId);
      let alarmCategoryFarmData = this.alarmCategoryFarmDatas.find(o => o.alarmCategoryId === alarmCategoryId);

      if (alarmCategoryData != null) {
        // 获得该报警分类下的所有故障
        let categoryDatas = Object.getOwnPropertyDescriptor(categoryGroups, categoryId).value as FaultTableData[];
        // let categoryDatas = Object.getOwnPropertyDescriptor(categoryGroups, categoryId).value as FaultData[];
        // 给故障数据重新赋值报警等级颜色和名称
        // 这样做可以使报警呈现的颜色和声音是客户端需要的配置
        categoryDatas.forEach(categoryData => {
          let level = this.faultLevels.find(o => o.faultLevelId === categoryData.faultLevelId);
          if (level != null) {
            categoryData.faultLevelColor = level.faultLevelColor;
            categoryData.faultLevelName = level.faultLevelName;
            if (!categoryData.confirm) {
              //更新当前报警等级
              if (this.currMaxFaultLevel == null) {
                this.currMaxFaultLevel = level
              }
              else if (this.currMaxFaultLevel.faultLevelWeight < level.faultLevelWeight) {
                this.currMaxFaultLevel = level;
              }
            }
          }
          // 插入本地存放报警集合对象中
          // alarmCategoryData.faultDatas.splice(0, 0, categoryData);
          alarmCategoryData.faultTableDatas.splice(0, 0, categoryData);
        });

      }
    });



    this.alarmCategoryDatas.forEach((item, index) => {
      // this.allAlarmCategoryDatas[index].faultTableDatas.unshift(...item.faultTableDatas);
      if (this.allAlarmCategoryDatas[index].faultTableDatas.length > this.alarmShowCount) {
        this.allAlarmCategoryDatas[index].faultTableDatas.slice(0, this.alarmShowCount);
      }
      this.alarmCategoryFarmDatas[index].farmFaultDatas.forEach((farmDatas) => {
        farmDatas.faultFTableDatas = this.allAlarmCategoryDatas[index].faultTableDatas.filter(o => o.farmId === farmDatas.farmId);
      });
    });

    this.clearAlarmCategoryMore();
    this.totalUnConfirmAlarm();
    this.beginAlarm(this.currMaxFaultLevel);
    clearTimeout(timer);
    /* let farmList = new List<FaultTableData>(categoryDatas);
        // let farmList = new List<FaultData>(categoryDatas);
        // 按风场分组
        let farmGroups = farmList.GroupBy(g => g.farmId, m => m);
        // 获得风场Id,
        let farmIds = Object.getOwnPropertyNames(farmGroups);
        farmIds.forEach(farmId => {
          try {
            let id: number = Number.parseInt(farmId);
            // 根据报风场Id,查询该风场在本地存放的报警对象
            let farmFaultData = alarmCategoryFarmData.farmFaultDatas.find(o => o.farmId == id);
            let farmDatas = Object.getOwnPropertyDescriptor(farmGroups, farmId).value as FaultTableData[];
            // let farmDatas = Object.getOwnPropertyDescriptor(farmGroups, farmId).value as FaultData[];
            farmDatas.forEach(farmData => {
              farmFaultData.faultFTableDatas.splice(0, 0, farmData);
            });

          }
          catch (error) {
            console.log("subscribeAlarm has error", error);
          }
    }); */
    this.alarmCategoryFilter();

  }

  /**
 * 过滤(模糊查询)
 */
  alarmCategoryFilter() {
    this.alarmCategoryDatas[0].faultTableDatas = this.allAlarmCategoryDatas[0].faultTableDatas.filter(data => new RegExp("\s+|" + this.desc).test(data.desc) && new RegExp("\s+|" + this.components).test(data.components) && new RegExp("\s+|" + this.faultLevelName).test(data.faultLevelName))
    // this.alarmCategoryDatas[0].faultTableDatas = this.allAlarmCategoryDatas[0].faultTableDatas.filter(data =>data.desc.includes(this.desc) && data.components==this.components && data.faultLevelName.includes(this.faultLevelName))


  }


  lastTimer: any;
  /**
   * 开始报警
   *
   * @param {FaultLevel} level
   * @memberof AlarmLampComponent
   */
  private beginAlarm(level: FaultLevel) {
    if (this.lastTimer) {
      clearTimeout(this.lastTimer);
    }
    this.audio.forEach(v => {
      v.pause();
    });

    if (level) {
      //是否播放报警声音
      if (this.isSound == true) {
        this.audio.forEach(val => {
          if (level.content && val.src == level.content.toString()) {
            val.replay();
            this.lastTimer = setTimeout(() => {
              val.pause();
              this.isAlarm = false;
            }, this.lastTime * 1000);
          }
        });
      }
      //是否闪烁报警灯
      if (this.isLedFlash == true) {
        this.isAlarm = false;
        setTimeout(() => {
          this.isAlarm = true;
        });

      }
      //是否自动弹出报警框
      if (this.isShowWindow == true) {
        if (!this.fadeDiv) {
          this.fadeDiv = true;
        }
      }
    }
  }


  /**
   * 结束报警
   *
   * @memberof AlarmLampComponent
   */
  private endAlarm() {
    this.isAlarm = false;
    this.audio.forEach(v => {
      v.pause();
    })
  }


  /**
   * 统计未确认报警数量
   *
   * @memberof AlarmLampComponent
   */
  private totalUnConfirmAlarm() {
    //用来临时存放未确认的报警条数
    let total = 0;
    // this.alarmCategoryDatas.forEach(o => {
    //   let list = new List(o.faultDatas);
    //   total += list.Count(f => !f.confirm);
    // });
    this.alarmCategoryDatas.forEach(o => {
      let list = new List(o.faultTableDatas);
      total += list.Count(f => !f.confirm);
    });
    this.alarmTotal = total;
    // this.alarmCategoryDatas.sort(function(a,b){return Date.parse(a['faultTime']) -Date.parse(b['faultTime'])})


    this.alarmCategoryFarmDatas.forEach(a => {
      a.farmFaultDatas.forEach(f => {
        f.confirmTotal = 0;
        f.faultFTableDatas.forEach(o => {
          if (!o.confirm) {
            f.confirmTotal += 1;
          }
        })
      })
    })


  }
  /**
   * 关闭alarm弹框
   *
   * @memberof AlarmLampComponent
   */
  public onClickCloseAlarm() {
    this.fadeDiv = false;
  }

  /**
   * tab切换（点击 预警、报警切换事件）
   *
   * @memberof AlarmLampComponent
   */
  isActive(number) {
    // this.active = (number == 1) ? true : false;
    switch (number) {
      case 1:
        this.active1 = true;
        this.active2 = false;
        this.active3 = false;
        break;
      case 2:
        this.active1 = false;
        this.active2 = true;
        this.active3 = false;
        break;
      default:
        this.active1 = false;
        this.active2 = false;
        this.active3 = true;
    }
  }
}
interface AudioData {
  audioId: number,
  audioSrc: string,
  volume: number,
  muted?: boolean,
}



// WEBPACK FOOTER //
// ./src/app/module/navigation/alarm-lamp/alarm-lamp.component.ts
